import os

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.select import Select
import time
from util.basedir import SCREENSHOT_DIR
from util.common import logger


class Base:
    def __init__(self, driver: webdriver.Edge):
        self.driver = driver
        self.logger = logger  # 引入日志

    def open_url(self, url):
        """打开URL"""
        self.driver.get(url)
        self.logger.info(f"打开URL: {url}")

    def loc_ele(self, loc: tuple) -> webdriver.remote.webelement.WebElement:
        """定位单个元素（loc格式：(By.XXX, "value")）"""
        try:
            ele = self.driver.find_element(*loc)
            self.logger.info(f"成功定位元素: {loc}")
            return ele
        except Exception as e:
            self.logger.error(f"定位元素失败: {loc}, 错误: {str(e)}")
            raise

    def loc_eles(self, loc: tuple) -> list:
        """定位多个元素"""
        try:
            eles = self.driver.find_elements(*loc)
            self.logger.info(f"成功定位元素列表: {loc}, 共{len(eles)}个元素")
            return eles
        except Exception as e:
            self.logger.error(f"定位元素列表失败: {loc}, 错误: {str(e)}")
            raise

    def loc_wait_ele(self, loc: tuple, timeout=15, poll_frequency=1) -> webdriver.remote.webelement.WebElement:
        """显示等待元素可点击（考核要求）"""
        try:
            ele = WebDriverWait(
                self.driver, timeout=timeout, poll_frequency=poll_frequency
            ).until(EC.element_to_be_clickable(loc))
            self.logger.info(f"等待并定位元素: {loc}")
            return ele
        except Exception as e:
            self.logger.error(f"等待元素失败: {loc}, 错误: {str(e)}")
            raise

    def capture_screenshot(self, filename: str) -> str:
        """截图（按时间命名，保存到screenshots目录）"""
        screenshot_name = f"{time.strftime('%Y%m%d%H%M%S')}_{filename}"
        screenshot_path = os.path.join(SCREENSHOT_DIR, screenshot_name)
        try:
            self.driver.save_screenshot(screenshot_path)
            self.logger.info(f"截图保存路径: {screenshot_path}")
            return screenshot_path
        except Exception as e:
            self.logger.error(f"截图失败: {str(e)}")
            raise

    # ------------------------------ 鼠标事件 ------------------------------
    def hover_ele(self, loc: tuple):
        """鼠标悬停"""
        ele = self.loc_ele(loc)
        ActionChains(self.driver).move_to_element(ele).perform()
        self.logger.info(f"鼠标悬停元素: {loc}")

    def double_click(self, loc: tuple):
        """双击元素"""
        ele = self.loc_ele(loc)
        ActionChains(self.driver).double_click(ele).perform()
        self.logger.info(f"双击元素: {loc}")

    def right_click(self, loc: tuple):
        """右键点击元素"""
        ele = self.loc_ele(loc)
        ActionChains(self.driver).context_click(ele).perform()
        self.logger.info(f"右键点击元素: {loc}")

    # ------------------------------ 键盘事件 ------------------------------
    def send_enter(self, loc: tuple):
        """发送回车键"""
        ele = self.loc_ele(loc)
        ele.send_keys(Keys.ENTER)
        self.logger.info(f"向元素{loc}发送回车键")

    def send_ctrl_a(self, loc: tuple):
        """全选（Ctrl+A）"""
        ele = self.loc_ele(loc)
        ele.send_keys(Keys.CONTROL, "A")
        self.logger.info(f"向元素{loc}发送Ctrl+A")

    def send_ctrl_c(self, loc: tuple):
        """复制（Ctrl+C）"""
        ele = self.loc_ele(loc)
        ele.send_keys(Keys.CONTROL, "C")
        self.logger.info(f"向元素{loc}发送Ctrl+C")

    def send_ctrl_v(self, loc: tuple):
        """粘贴（Ctrl+V）"""
        ele = self.loc_ele(loc)
        ele.send_keys(Keys.CONTROL, "V")
        self.logger.info(f"向元素{loc}发送Ctrl+V")

    # ------------------------------ 框架/窗口切换 ------------------------------
    def switch_iframe(self, loc: tuple):
        """切换到iframe"""
        ele = self.loc_ele(loc)
        self.driver.switch_to.frame(ele)
        self.logger.info(f"切换到iframe: {loc}")

    def switch_default_content(self):
        """退出iframe（回到默认页面）"""
        self.driver.switch_to.default_content()
        self.logger.info("退出iframe，回到默认页面")

    def switch_window(self, index: int):
        """切换窗口（index：窗口索引，0为第一个窗口）"""
        windows = self.driver.window_handles
        if index >= len(windows):
            raise IndexError(f"窗口索引{index}超出范围，当前仅{len(windows)}个窗口")
        self.driver.switch_to.window(windows[index])
        self.logger.info(f"切换到第{index+1}个窗口")

    # ------------------------------ 弹框处理 ------------------------------
    def alert_accept(self):
        """确认弹框（Alert-OK）"""
        alert = self.driver.switch_to.alert
        alert.accept()
        self.logger.info("确认Alert弹框")

    def alert_dismiss(self):
        """取消弹框（Alert-Cancel）"""
        alert = self.driver.switch_to.alert
        alert.dismiss()
        self.logger.info("取消Alert弹框")

    # ------------------------------ 下拉框处理 ------------------------------
    def select_by_index(self, loc: tuple, index: int):
        """下拉框按索引选择"""
        ele = self.loc_ele(loc)
        Select(ele).select_by_index(index)
        self.logger.info(f"下拉框{loc}按索引{index}选择")

    def select_by_value(self, loc: tuple, value: str):
        """下拉框按value选择"""
        ele = self.loc_ele(loc)
        Select(ele).select_by_value(value)
        self.logger.info(f"下拉框{loc}按value{value}选择")

    # ------------------------------ 滚动条处理 ------------------------------
    def scroll_to_ele(self, loc: tuple):
        """滚动到指定元素可见"""
        ele = self.loc_ele(loc)
        self.driver.execute_script("arguments[0].scrollIntoView();", ele)
        self.logger.info(f"滚动到元素{loc}可见")

    def scroll_to_bottom(self):
        """滚动到页面底部"""
        self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
        self.logger.info("滚动到页面底部")